home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 2
/
AACD 2.iso
/
AACD
/
Programming
/
fpc
/
compiler
/
types.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-09-24
|
38KB
|
1,029 lines
{
$Id: types.pas,v 1.2.2.2 1998/04/27 23:07:02 peter Exp $
Copyright (C) 1993-98 by Florian Klaempfl
This unit provides some help routines for type handling
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit types;
interface
uses
objects,cobjects,globals,symtable,tree,aasm;
type
tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit,
mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle);
{ returns true, if def defines an ordinal type }
function is_ordinal(def : pdef) : boolean;
{ true if p points to an open array def }
function is_open_array(p : pdef) : boolean;
{ returns true, if def defines a signed data type (only for ordinal types) }
function is_signed(def : pdef) : boolean;
{ returns true, if def uses FPU }
function is_fpu(def : pdef) : boolean;
{ true if the return value is in EAX }
function ret_in_acc(def : pdef) : boolean;
{ true if uses a parameter as return value }
function ret_in_param(def : pdef) : boolean;
{ true if a const parameter is too large to copy }
function dont_copy_const_param(def : pdef) : boolean;
{ true if we must never copy this parameter }
const
never_copy_const_param : boolean = false;
{ true, if def1 and def2 are semantical the same }
function is_equal(def1,def2 : pdef) : boolean;
{ checks for type compatibility (subgroups of type) }
{ used for case statements... probably missing stuff }
{ to use on other types }
function is_subequal(def1, def2: pdef): boolean;
{ true, if two parameter lists are equal }
function equal_paras(def1,def2 : pdefcoll) : boolean;
{ gibt den ordinalen Werten der Node zurueck oder falls sie }
{ keinen ordinalen Wert hat, wird ein Fehler erzeugt }
function get_ordinal_value(p : ptree) : longint;
{ if l isn't in the range of def a range check error is generated }
procedure testrange(def : pdef;l : longint);
{ returns the range of def }
procedure getrange(def : pdef;var l : longint;var h : longint);
{ generates a VMT for _class }
procedure genvmt(_class : pobjectdef);
{ true, if p is a pointer to a const int value }
function is_constintnode(p : ptree) : boolean;
{ like is_constintnode }
function is_constboolnode(p : ptree) : boolean;
function is_constrealnode(p : ptree) : boolean;
function is_constcharnode(p : ptree) : boolean;
{ some type helper routines for MMX support }
function is_mmx_able_array(p : pdef) : boolean;
{ returns the mmx type }
function mmx_type(p : pdef) : tmmxtype;
implementation
uses verbose;
function is_constintnode(p : ptree) : boolean;
begin
{DM: According to me, an orddef with anysize, is
a correct constintnode. Anyway I commented changed s32bit check,
because it caused problems with statements like a:=high(word).}
is_constintnode:=((p^.treetype=ordconstn) and
(p^.resulttype^.deftype=orddef) and
(porddef(p^.resulttype)^.typ in [u8bit,s8bit,u16bit,s16bit,
u32bit,s32bit,uauto]));
end;
function is_constcharnode(p : ptree) : boolean;
begin
is_constcharnode:=((p^.treetype=ordconstn) and
(p^.resulttype^.deftype=orddef) and
(porddef(p^.resulttype)^.typ=uchar));
end;
function is_constrealnode(p : ptree) : boolean;
begin
is_constrealnode:=(p^.treetype=realconstn);
end;
function is_constboolnode(p : ptree) : boolean;
begin
is_constboolnode:=((p^.treetype=ordconstn) and
(p^.resulttype^.deftype=orddef) and
(porddef(p^.resulttype)^.typ=bool8bit));
end;
function equal_paras(def1,def2 : pdefcoll) : boolean;
begin
while (assigned(def1)) and (assigned(def2)) do
begin
if not(is_equal(def1^.data,def2^.data)) or
(def1^.paratyp<>def2^.paratyp) then
begin
equal_paras:=false;
exit;
end;
def1:=def1^.next;
def2:=def2^.next;
end;
if (def1=nil) and (def2=nil) then
equal_paras:=true
else
equal_paras:=false;
end;
{ returns true, if def uses FPU }
function is_fpu(def : pdef) : boolean;
begin
is_fpu:=(def^.deftype=floatdef) and (pfloatdef(def)^.typ<>f32bit);
end;
function is_ordinal(def : pdef) : boolean;
var
dt : tbasetype;
begin
case def^.deftype of
orddef : begin
dt:=porddef(def)^.typ;
is_ordinal:=(dt=s32bit) or (dt=u32bit) or (dt=uchar) or (dt=u8bit) or
(dt=s8bit) or (dt=s16bit) or (dt=bool8bit) or (dt=u16bit);
end;
enumdef : is_ordinal:=true;
else is_ordinal:=false;
end;
end;
function is_signed(def : pdef) : boolean;
var
dt : tbasetype;
begin
case def^.deftype of
orddef : begin
dt:=porddef(def)^.typ;
is_signed:=(dt=s32bit) or (dt=s8bit) or (dt=s16bit);
end;
enumdef : is_signed:=false;
else internalerror(1001);
end;
end;
{ true, if p points to an open array def }
function is_open_array(p : pdef) : boolean;
begin
is_open_array:=(p^.deftype=arraydef) and
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=-1);
end;
{ true if the return value is in accumulator (EAX for i386), D0 for 68k }
function ret_in_acc(def : pdef) : boolean;
begin
ret_in_acc:=(def^.deftype=orddef) or
(def^.deftype=pointerdef) or
(def^.deftype=enumdef) or
(def^.deftype=procvardef) or
(def^.deftype=classrefdef) or
((def^.deftype=objectdef) and
((pobjectdef(def)^.options and oois_class)<>0)
) or
((def^.deftype=setdef) and
(psetdef(def)^.settype=smallset)) or
((def^.deftype=floatdef) and
(pfloatdef(def)^.typ=f32bit));
end;
{ true if uses a parameter as return value }
function ret_in_param(def : pdef) : boolean;
begin
ret_in_param:=(def^.deftype=arraydef) or
(def^.deftype=stringdef) or
((def^.deftype=objectdef) and
((pobjectdef(def)^.options and oois_class)=0)
) or
(def^.deftype=recorddef) or
((def^.deftype=setdef) and
(psetdef(def)^.settype<>smallset));
end;
{ true if a const parameter is too large to copy }
function dont_copy_const_param(def : pdef) : boolean;
begin
dont_copy_const_param:=(def^.deftype=arraydef) or
(def^.deftype=stringdef) or
(def^.deftype=objectdef) or
(def^.deftype=formaldef) or
(def^.deftype=recorddef) or
(def^.deftype=formaldef) or
((def^.deftype=setdef) and
(psetdef(def)^.settype<>smallset));
end;
procedure testrange(def : pdef;l : longint);
var
lv,hv: longint;
begin
getrange(def,lv,hv);
if (def^.deftype=orddef) and
(porddef(def)^.typ=u32bit) then
begin
if lv<=hv then
begin
if (l<lv) or (l>hv) then
Message(parser_e_range_check_error);
end
else
{ this happens with the wrap around problem }
{ if lv is positive and hv is over $7ffffff }
{ so it seems negative }
begin
if ((l>=0) and (l<lv)) or
((l<0) and (l>hv)) then
Message(parser_e_range_check_error);
end;
end
else if (l<lv) or (l>hv) then
Message(parser_e_range_check_error);
end;
procedure getrange(def : pdef;var l : longint;var h : longint);
begin
if def^.deftype=orddef then
case porddef(def)^.typ of
s32bit,s16bit,u16bit,s8bit,u8bit :
begin
l:=porddef(def)^.von;
h:=porddef(def)^.bis;
end;
bool8bit : begin
l:=0;
h:=1;
end;
uchar : begin
l:=0;
h:=255;
end;
u32bit : begin
{ this should work now }
l:=porddef(def)^.von;
h:=porddef(def)^.bis;
end;
end
else
if def^.deftype=enumdef then
begin
l:=0;
h:=penumdef(def)^.max;
end;
end;
function get_ordinal_value(p : ptree) : longint;
begin
if p^.treetype=ordconstn then
get_ordinal_value:=p^.value
else
Message(parser_e_ordinal_expected);
end;
function mmx_type(p : pdef) : tmmxtype;
begin
mmx_type:=mmxno;
if is_mmx_able_array(p) then
begin
if parraydef(p)^.definition^.deftype=floatdef then
case pfloatdef(parraydef(p)^.definition)^.typ of
s32real:
mmx_type:=mmxsingle;
f16bit:
mmx_type:=mmxfixed16
end
else
case porddef(parraydef(p)^.definition)^.typ of
u8bit:
mmx_type:=mmxu8bit;
s8bit:
mmx_type:=mmxs8bit;
u16bit:
mmx_type:=mmxu16bit;
s16bit:
mmx_type:=mmxs16bit;
u32bit:
mmx_type:=mmxu32bit;
s32bit:
mmx_type:=mmxs32bit;
end;
end;
end;
function is_mmx_able_array(p : pdef) : boolean;
begin
{$ifdef SUPPORT_MMX}
if (cs_mmx_saturation in aktswitches) then
begin
is_mmx_able_array:=(p^.deftype=arraydef) and
(
((parraydef(p)^.definition^.deftype=orddef) and
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=1) and
(porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
) or
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=3) and
(porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
)
)
) or
(
((parraydef(p)^.definition^.deftype=floatdef) and
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=3) and
(pfloatdef(parraydef(p)^.definition)^.typ=f16bit)
) or
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=1) and
(pfloatdef(parraydef(p)^.definition)^.typ=s32real)
)
)
);
end
else
begin
is_mmx_able_array:=(p^.deftype=arraydef) and
(
((parraydef(p)^.definition^.deftype=orddef) and
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=1) and
(porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit])
) or
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=3) and
(porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit])
) or
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=7) and
(porddef(parraydef(p)^.definition)^.typ in [u8bit,s8bit])
)
)
) or
(
((parraydef(p)^.definition^.deftype=floatdef) and
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=3) and
(pfloatdef(parraydef(p)^.definition)^.typ=f32bit)
)
or
(
(parraydef(p)^.lowrange=0) and
(parraydef(p)^.highrange=1) and
(pfloatdef(parraydef(p)^.definition)^.typ=s32real)
)
)
);
end;
{$else SUPPORT_MMX}
is_mmx_able_array:=false;
{$endif SUPPORT_MMX}
end;
function is_equal(def1,def2 : pdef) : boolean;
var
b : boolean;
hd : pdef;
hp1,hp2 : pdefcoll;
begin
{ both types must exists }
if not (assigned(def1) and assigned(def2)) then
begin
is_equal:=false;
exit;
end;
{ be sure, that if there is a stringdef, that this is def1 }
if def2^.deftype=stringdef then
begin
hd:=def1;
def1:=def2;
def2:=hd;
end;
b:=false;
{ wenn beide auf die gleiche Definition zeigen sind sie wohl gleich...}
if def1=def2 then
b:=true
else
{ pointer with an equal definition are equal }
if (def1^.deftype=pointerdef) and (def2^.deftype=pointerdef) then
{ here a problem detected in tabsolutesym }
{ the types can be forward type !! }
begin
if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
b:=(def1^.sym=def2^.sym)
else
b:=is_equal(ppointerdef(def1)^.definition,ppointerdef(def2)^.definition);
end
else
{ Grundtypen sind gleich, wenn sie den selben Grundtyp haben, }
{ und wenn noetig den selben Unterbereich haben }
if (def1^.deftype=orddef) and (def2^.deftype=orddef) then
begin
case porddef(def1)^.typ of
u32bit,u8bit,s32bit,s8bit,u16bit,s16bit : begin
if porddef(def1)^.typ=porddef(def2)^.typ then
if (porddef(def1)^.von=porddef(def2)^.von) and
(porddef(def1)^.bis=porddef(def2)^.bis) then
b:=true;
end;
uvoid,bool8bit,uchar :
b:=porddef(def1)^.typ=porddef(def2)^.typ;
end;
end
else
if (def1^.deftype=floatdef) and (def2^.deftype=floatdef) then
b:=pfloatdef(def1)^.typ=pfloatdef(def2)^.typ
else
{ strings with the same length are equal }
if (def1^.deftype=stringdef) and (def2^.deftype=stringdef) and
(pstringdef(def1)^.len=pstringdef(def2)^.len) then
b:=true
{ STRING[N] ist equivalent zu ARRAY[0..N] OF CHAR (N<256) }
{
else if ((def1^.deftype=stringdef) and (def2^.deftype=arraydef)) and
(parraydef(def2)^.definition^.deftype=orddef) and
(porddef(parraydef(def1)^.definition)^.typ=uchar) and
(parraydef(def2)^.lowrange=0) and
(parraydef(def2)^.highrange=pstringdef(def1)^.len) then
b:=true }
else
if (def1^.deftype=formaldef) and (def2^.deftype=formaldef) then
b:=true
{ file types with the same file element type are equal }
{ this is a problem for assign !! }
{ changed to allow if one is untyped }
{ all typed files are equal to the special }
{ typed file that has voiddef as elemnt type }
{ but must NOT match for text file !!! }
else
if (def1^.deftype=filedef) and (def2^.deftype=filedef) then
b:=(pfiledef(def1)^.filetype=pfiledef(def2)^.filetype) and
((
((pfiledef(def1)^.typed_as=nil) and
(pfiledef(def2)^.typed_as=nil)) or
(
(pfiledef(def1)^.typed_as<>nil) and
(pfiledef(def2)^.typed_as<>nil) and
is_equal(pfiledef(def1)^.typed_as,pfiledef(def2)^.typed_as)
) or
( (pfiledef(def1)^.typed_as=pdef(voiddef)) or
(pfiledef(def2)^.typed_as=pdef(voiddef))
)))
{ sets with the same element type are equal }
else
if (def1^.deftype=setdef) and (def2^.deftype=setdef) then
begin
if assigned(psetdef(def1)^.setof) and
assigned(psetdef(def2)^.setof) then
b:=is_equal(psetdef(def1)^.setof,psetdef(def2)^.setof)
else b:=true;
end
else
if (def1^.deftype=procvardef) and (def2^.deftype=procvardef) then
begin
{ poassembler isn't important for compatibility }
b:=((pprocvardef(def1)^.options and not(poassembler))=
(pprocvardef(def2)^.options and not(poassembler))
) and
is_equal(pprocvardef(def1)^.retdef,pprocvardef(def2)^.retdef);
{ now evalute the parameters }
if b then
begin
hp1:=pprocvardef(def1)^.para1;
hp2:=pprocvardef(def1)^.para1;
while assigned(hp1) and assigned(hp2) do
begin
if not(is_equal(hp1^.data,hp2^.data)) or
not(hp1^.paratyp=hp2^.paratyp) then
begin
b:=false;
break;
end;
hp1:=hp1^.next;
hp2:=hp2^.next;
end;
b:=(hp1=nil) and (hp2=nil);
end;
end
else
if (def1^.deftype=arraydef) and (def2^.deftype=arraydef) and
(is_open_array(def1) or is_open_array(def2)) then
begin
b:=is_equal(parraydef(def1)^.definition,parraydef(def2)^.definition);
end
else
if (def1^.deftype=classrefdef) and (def2^.deftype=classrefdef) then
begin
{ similar to pointerdef: }
if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then
b:=(def1^.sym=def2^.sym)
else
b:=is_equal(pclassrefdef(def1)^.definition,pclassrefdef(def2)^.definition);
end;
is_equal:=b;
end;
function is_subequal(def1, def2: pdef): boolean;
Begin
if assigned(def1) and assigned(def2) then
Begin
is_subequal := FALSE;
if (def1^.deftype = orddef) and (def2^.deftype = orddef) then
Begin
{ see p.47 of Turbo Pascal 7.01 manual for the separation of types }
{ range checking for case statements is done with testrange }
case porddef(def1)^.typ of
s32bit,u32bit,u8bit,s8bit,s16bit,u16bit:
Begin
{ PROBABLE CODE GENERATION BUG HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
{ if porddef(def2)^.typ in [s32bit,u32bit,u8bit,s8bit,s16bit,u16bit] then
is_subequal := TRUE; }
if (porddef(def2)^.typ = s32bit) or
(porddef(def2)^.typ = u32bit) or
(porddef(def2)^.typ = u8bit) or
(porddef(def2)^.typ = s8bit) or
(porddef(def2)^.typ = s16bit) or
(porddef(def2)^.typ = u16bit) then
Begin
is_subequal:=TRUE;
end;
end;
bool8bit: if porddef(def2)^.typ = bool8bit then is_subequal := TRUE;
uchar: if porddef(def2)^.typ = uchar then is_subequal := TRUE;
end;
end
else
Begin
{ I assume that both enumerations are equal when the first }
{ pointers are equal. }
if (def1^.deftype = enumdef) and (def2^.deftype =enumdef) then
Begin
if penumdef(def1)^.first = penumdef(def2)^.first then
is_subequal := TRUE;
end;
end;
end; { endif assigned ... }
end;
type
pprocdefcoll = ^tprocdefcoll;
tprocdefcoll = record
next : pprocdefcoll;
data : pprocdef;
end;
psymcoll = ^tsymcoll;
tsymcoll = record
next : psymcoll;
name : pstring;
data : pprocdefcoll;
end;
var
wurzel : psymcoll;
nextvirtnumber : longint;
_c : pobjectdef;
has_constructor,has_virtual_method : boolean;
procedure eachsym(sym : psym);{$ifndef FPC}far;{$endif}
var
procdefcoll : pprocdefcoll;
hp : pprocdef;
symcoll : psymcoll;
_name : string;
stored : boolean;
begin
{ nur Unterprogrammsymbole werden in die VMT aufgenommen }
if sym^.typ=procsym then
begin
_name:=sym^.name;
symcoll:=wurzel;
while assigned(symcoll) do
begin
{ wenn das Symbol in der Liste schon existiert }
if _name=symcoll^.name^ then
begin
{ walk thorugh all defs of the symbol }
hp:=pprocsym(sym)^.definition;
while assigned(hp) do
begin
{ compare with all stored definitions }
procdefcoll:=symcoll^.data;
stored:=false;
while assigned(procdefcoll) do
begin
{ compare parameters }
if equal_paras(procdefcoll^.data^.para1,hp^.para1) and
(
((procdefcoll^.data^.options and povirtualmethod)<>0) or
((hp^.options and povirtualmethod)<>0)
) then
begin
{ wenn sie gleich sind }
{ und eine davon virtual deklariert ist }
{ Fehler falls nur eine VIRTUAL }
if (procdefcoll^.data^.options and povirtualmethod)<>
(hp^.options and povirtualmethod) then
Message1(parser_e_overloaded_are_not_both_virtual,_c^.name^+'.'+_name);
{ check, if the overridden directive is set }
{ (povirtualmethod is set! }
{ class ? }
if ((_c^.options and oois_class)<>0) and
((hp^.options and pooverridingmethod)=0) then
Message1(parser_w_should_use_override,_c^.name^+'.'+_name);
{ error, if the return types aren't equal }
if not(is_equal(procdefcoll^.data^.retdef,hp^.retdef)) then
Message1(parser_e_overloaded_methodes_not_same_ret,_c^.name^+'.'+_name);
{ the flags have to match }
{ except abstract and override }
if (procdefcoll^.data^.options and not(poabstractmethod or pooverridingmethod))<>
(hp^.options and not(poabstractmethod or pooverridingmethod)) then
Message1(parser_e_header_dont_match_forward,_c^.name^+'.'+_name);
{ now set the number }
hp^.extnumber:=procdefcoll^.data^.extnumber;
{ and exchange }
procdefcoll^.data:=hp;
stored:=true;
end;
procdefcoll:=procdefcoll^.next;
end;
{ if it isn't saved in the list }
{ we create a new entry }
if not(stored) then
begin
new(procdefcoll);
procdefcoll^.data:=hp;
procdefcoll^.next:=symcoll^.data;
symcoll^.data:=procdefcoll;
{ if the method is virtual ... }
if (hp^.options and povirtualmethod)<>0 then
begin
{ ... it will get a number }
hp^.extnumber:=nextvirtnumber;
inc(nextvirtnumber);
end;
{ check, if a method should be overridden }
if (hp^.options and pooverridingmethod)<>0 then
Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
end;
hp:=hp^.nextoverloaded;
end;
exit;
end;
symcoll:=symcoll^.next;
end;
{ if not, generate a new symbol item }
new(symcoll);
symcoll^.name:=stringdup(sym^.name);
symcoll^.next:=wurzel;
symcoll^.data:=nil;
wurzel:=symcoll;
hp:=pprocsym(sym)^.definition;
{ inserts all definitions }
while assigned(hp) do
begin
new(procdefcoll);
procdefcoll^.data:=hp;
procdefcoll^.next:=symcoll^.data;
symcoll^.data:=procdefcoll;
{ if it's a virtual method }
if (hp^.options and povirtualmethod)<>0 then
begin
{ then it gets a number ... }
hp^.extnumber:=nextvirtnumber;
{ and we inc the number }
inc(nextvirtnumber);
has_virtual_method:=true;
end;
if (hp^.options and poconstructor)<>0 then
has_constructor:=true;
{ check, if a method should be overridden }
if (hp^.options and pooverridingmethod)<>0 then
Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name);
{ next overloaded method }
hp:=hp^.nextoverloaded;
end;
end;
end;
procedure genvmt(_class : pobjectdef);
procedure do_genvmt(p : pobjectdef);
begin
{ start with the base class }
if assigned(p^.childof) then
do_genvmt(p^.childof);
{ walk through all public syms }
_c:=_class;
{$ifdef tp}
p^.publicsyms^.foreach(eachsym);
{$else}
p^.publicsyms^.foreach(@eachsym);
{$endif}
end;
var
symcoll : psymcoll;
procdefcoll : pprocdefcoll;
i : longint;
begin
wurzel:=nil;
nextvirtnumber:=0;
has_constructor:=false;
has_virtual_method:=false;
{ generates a tree of all used methods }
do_genvmt(_class);
if has_virtual_method and not(has_constructor) then
begin
exterror:=strpnew(_class^.name^);
Message(parser_w_virtual_without_constructor);
end;
{ generates the VMT }
{ walk trough all numbers for virtual methods and search }
{ the method }
for i:=0 to nextvirtnumber-1 do
begin
symcoll:=wurzel;
{ walk trough all symbols }
while assigned(symcoll) do
begin
{ walk trough all methods }
procdefcoll:=symcoll^.data;
while assigned(procdefcoll) do
begin
{ writes the addresses to the VMT }
{ but only this which are declared as virtual }
if procdefcoll^.data^.extnumber=i then
begin
if (procdefcoll^.data^.options and povirtualmethod)<>0 then
begin
{ if a method is abstract, then is also the }
{ class abstract and it's not allow to }
{ generates an instance }
if (procdefcoll^.data^.options and poabstractmethod)<>0 then
begin
_class^.options:=_class^.options or oois_abstract;
datasegment^.concat(new(pai_const,init_symbol('ABSTRACTERROR')));
end
else
begin
datasegment^.concat(new(pai_const,init_symbol(
strpnew(procdefcoll^.data^.mangledname))));
if (procdefcoll^.data^.options and povirtualmethod)<>0 then
maybe_concat_external(procdefcoll^.data^.owner,
procdefcoll^.data^.mangledname);
end;
end;
end;
procdefcoll:=procdefcoll^.next;
end;
symcoll:=symcoll^.next;
end;
end;
{ disposes the above generated tree }
symcoll:=wurzel;
while assigned(symcoll) do
begin
wurzel:=symcoll^.next;
stringdispose(symcoll^.name);
procdefcoll:=symcoll^.data;
while assigned(procdefcoll) do
begin
symcoll^.data:=procdefcoll^.next;
dispose(procdefcoll);
procdefcoll:=symcoll^.data;
end;
dispose(symcoll);
symcoll:=wurzel;
end;
end;
end.
{
$Log: types.pas,v $
Revision 1.2.2.2 1998/04/27 23:07:02 peter
* small message fixes
Revision 1.2.2.1 1998/04/08 11:38:44 peter
* nasm patches, pierres symtable patch
Revision 1.2 1998/03/28 23:09:57 florian
* secondin bugfix (m68k and i386)
* overflow checking bugfix (m68k and i386) -- pretty useless in
secondadd, since everything is done using 32-bit
* loading pointer to routines hopefully fixed (m68k)
* flags problem with calls to RTL internal routines fixed (still strcmp
to fix) (m68k)
* #ELSE was still incorrect (didn't take care of the previous level)
* problem with filenames in the command line solved
* problem with mangledname solved
* linking name problem solved (was case insensitive)
* double id problem and potential crash solved
* stop after first error
* and=>test problem removed
* correct read for all float types
* 2 sigsegv fixes and a cosmetic fix for Internal Error
* push/pop is now correct optimized (=> mov (%esp),reg)
Revision 1.1.1.1 1998/03/25 11:18:15 root
* Restored version
Revision 1.24 1998/03/21 23:59:40 florian
* indexed properties fixed
* ppu i/o of properties fixed
* field can be also used for write access
* overriding of properties
Revision 1.23 1998/03/20 23:31:35 florian
* bug0113 fixed
* problem with interdepened units fixed ("options.pas problem")
* two small extensions for future AMD 3D support
Revision 1.22 1998/03/10 01:17:30 peter
* all files have the same header
* messages are fully implemented, EXTDEBUG uses Comment()
+ AG... files for the Assembler generation
Revision 1.21 1998/03/06 01:09:01 peter
* removed the conflicts that had occured
Revision 1.20 1998/03/06 00:53:01 peter
* replaced all old messages from errore.msg, only ExtDebug and some
Comment() calls are left
* fixed options.pas
Revision 1.19 1998/03/05 22:40:56 florian
+ warning about missing constructor added
Revision 1.18 1998/03/04 17:34:14 michael
+ Changed ifdef FPK to ifdef FPC
Revision 1.17 1998/03/02 01:49:38 peter
* renamed target_DOS to target_GO32V1
+ new verbose system, merged old errors and verbose units into one new
verbose.pas, so errors.pas is obsolete
Revision 1.16 1998/02/13 10:35:55 daniel
* Made Motorola version compilable.
* Fixed optimizer
Revision 1.15 1998/02/12 17:19:33 florian
* fixed to get remake3 work, but needs additional fixes (output, I don't like
also that aktswitches isn't a pointer)
Revision 1.14 1998/02/12 11:50:52 daniel
Yes! Finally! After three retries, my patch!
Changes:
Complete rewrite of psub.pas.
Added support for DLL's.
Compiler requires less memory.
Platform units for each platform.
Revision 1.13 1998/02/11 21:56:41 florian
* bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
Revision 1.12 1998/02/07 23:05:08 florian
* once more MMX
Revision 1.11 1998/02/06 10:34:35 florian
* bug0082 and bug0084 fixed
Revision 1.10 1998/02/05 22:27:07 florian
* small problems fixed: remake3 should now work
Revision 1.9 1998/02/05 21:54:36 florian
+ more MMX
Revision 1.8 1998/01/31 00:43:37 carl
- removed in in is_subequal, because the code generator is buggy!
(instead uses if...)
Revision 1.7 1998/01/16 18:03:21 florian
* small bug fixes, some stuff of delphi styled constructores added
Revision 1.6 1998/01/11 19:24:35 carl
+ type checking routine (is_subequal) for case statements
Revision 1.5 1998/01/09 23:08:38 florian
+ C++/Delphi styled //-comments
* some bugs in Delphi object model fixed
+ override directive
Revision 1.4 1998/01/09 16:08:24 florian
* abstract methods call now abstracterrorproc if they are called
a class with an abstract method can be create with a class reference else
the compiler forbides this
Revision 1.3 1998/01/07 00:17:12 michael
Restored released version (plus fixes) as current
Revision 1.2 1997/11/28 18:14:51 pierre
working version with several bug fixes
Revision 1.1.1.1 1997/11/27 08:33:03 michael
FPC Compiler CVS start
Pre-CVS log:
CEC Carl-Eric Codere
FK Florian Klaempfl
PM Pierre Muller
+ feature added
- removed
* bug fixed or changed
History:
22th september 1997
+ function dont_copy_const_param added (FK)
25th september 1997
+ is_open_array added (FK)
+ is_equal handles now also open arrays (FK)
2nd october 1997
+ added then boolean never_copy_const_param for use in typed write
where we must push the reference anyway (PM)
3rd october 1997:
+ renamed ret_in_eax to ret_in_acc (for accumulator for port.) (CEC)
- removed reference to i386 unit (CEC)
25th october 1997:
* poassembler isn't important for compatiblity of proc vars (FK)
3rd november 1997:
+ added formaldef type to types where we dont_copy_const_param (PM)
20rd november 1997:
+ added is_fpu function (PM)
}